package com.spyu.utils;

import org.apache.commons.codec.binary.Base64;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class RSAUtils {

    private final static String ALGORITHM_RSA = "RSA";
    private final static String ALGORITHM_MD5_WITH_RSA = "MD5withRSA";

    /**
     * RSA签名，签名
     *
     * @param rsaPrivateKeyArr 私钥
     * @param data             待签名数据
     */
    public static byte[] signData(byte[] rsaPrivateKeyArr, String data) throws Exception {
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(rsaPrivateKeyArr);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
        //根据提供的密钥规范（密钥材料）生成私钥对象。
        PrivateKey key = keyFactory.generatePrivate(keySpec);
        //Signature类用于提供数字签名，用于保证数据的完整性，用非对称密钥中的私钥签名，公钥验签。
        //与 Java Security 中其他基于算法的类一样，Signature 提供了与实现无关的算法，因此，调用方（应用程序代码）
        // 会请求特定的签名算法并将它传回给已被正确初始化的 Signature 对象。如果需要，还可以通过特定的提供程序请求特定的算法
        //getInstance指定签名算法
        Signature signature = Signature.getInstance(ALGORITHM_MD5_WITH_RSA);
        //初始化签署签名的私钥
        signature.initSign(key);
        //根据初始化类型，这可更新要签名或验证的字节
        signature.update(data.getBytes());
        //signature.sign()签署或验证所有更新字节的签名
        return signature.sign();
    }

    /**
     * 验签
     *
     * @param rsaPublicKeyArr 公钥
     * @param src             原始字符串
     * @param sign            签名
     */
    public static boolean verifySign(byte[] rsaPublicKeyArr, String src, String sign) throws Exception {
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(rsaPublicKeyArr);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
        PublicKey key = keyFactory.generatePublic(keySpec);
        Signature signature = Signature.getInstance(ALGORITHM_MD5_WITH_RSA);
        signature.initVerify(key);
        signature.update(src.getBytes());
        byte[] decodeSignArr = Base64.decodeBase64(sign.getBytes());
        //signature.verify签署或验证所有更新字节的签名
        return signature.verify(decodeSignArr);

    }

}
